package com.zwg.tingshu.payment.service.impl;

import com.zwg.tingshu.common.util.AuthContextHolder;
import com.zwg.tingshu.model.payment.PaymentInfo;
import com.zwg.tingshu.payment.config.WxPayV3Config;
import com.zwg.tingshu.payment.service.PaymentInfoService;
import com.zwg.tingshu.payment.service.WxPayService;
import com.zwg.tingshu.payment.util.PayUtil;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wechat.pay.java.service.payments.jsapi.JsapiServiceExtension;
import com.wechat.pay.java.service.payments.jsapi.model.*;
import com.wechat.pay.java.service.payments.model.Transaction;
import io.seata.spring.annotation.GlobalTransactional;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;

@Service
@Slf4j
public class WxPayServiceImpl implements WxPayService {

	@Autowired
	private PaymentInfoService paymentInfoService;
	@Autowired
	private RSAAutoCertificateConfig rsaAutoCertificateConfig;
	@Autowired
	private WxPayV3Config wxPayV3Config;

	/**
	 * 用户付款成功后，处理微信支付异步回调
	 *
	 * @param request
	 * @return
	 */
	@Override
	@GlobalTransactional(rollbackFor = Exception.class)
	public Map<String, String> paySuccessNotify(HttpServletRequest request) {
		//1.从请求头中获取微信提交参数
		String wechatPaySerial = request.getHeader("Wechatpay-Serial"); //签名
		String nonce = request.getHeader("Wechatpay-Nonce"); //签名中的随机数
		String timestamp = request.getHeader("Wechatpay-Timestamp"); //时间戳
		String signature = request.getHeader("Wechatpay-Signature"); //签名类型
		//HTTP 请求体 body。切记使用原始报文，不要用 JSON 对象序列化后的字符串，避免验签的 body 和原文不一致。
		String requestBody = PayUtil.readData(request);
		//2.构建RequestParam请求参数对象
		RequestParam requestParam = new RequestParam.Builder()
				.serialNumber(wechatPaySerial)
				.nonce(nonce)
				.signature(signature)
				.timestamp(timestamp)
				.body(requestBody)
				.build();
		//3.// 初始化 NotificationParser 解析器对象
		NotificationParser parser = new NotificationParser(rsaAutoCertificateConfig);
		//4. 调用解析器对象解析方法 验签、解密 并转换成 Transaction
		Transaction transaction = parser.parse(requestParam, Transaction.class);
		if (transaction != null) {
			//4.1 业务验证，验证付款状态以及用户实际付款金额跟商户侧金额是否一致
			if (Transaction.TradeStateEnum.SUCCESS == transaction.getTradeState()) {
				Integer payerTotal = transaction.getAmount().getPayerTotal();
				//todo 调试阶段支付金额为1分，后续改为动态从本地交易记录中获取实际金额
				if (payerTotal.intValue() == 1) {
					//4.2 更新本地交易记录状态
					paymentInfoService.updatePaymentInfoSuccess(transaction);
					Map<String, String> map = new HashMap<>();
					map.put("code", "SUCCESS");
					map.put("message", "SUCCESS");
					return map;
				}
			}
		}
		return null;
	}

	/**
	 * 根据商户订单编号查询交易状态
	 *
	 * @param orderNo
	 * @return
	 */
	@Override
	public Boolean queryPayStatus(String orderNo) {
		//1.创建查询交易请求对象
		QueryOrderByOutTradeNoRequest queryOrderByOutTradeNoRequest = new QueryOrderByOutTradeNoRequest();
		queryOrderByOutTradeNoRequest.setMchid(wxPayV3Config.getMerchantId());
		queryOrderByOutTradeNoRequest.setOutTradeNo(orderNo);
		//2.创建调用微信服务端业务对象
		JsapiServiceExtension jsapiService = new JsapiServiceExtension.Builder().config(rsaAutoCertificateConfig).build();
		//3.调用微信查询交易状态接口
		Transaction transaction = jsapiService.queryOrderByOutTradeNo(queryOrderByOutTradeNoRequest);
		//4.解析响应结果返回交易状态
		if (transaction != null) {
			Transaction.TradeStateEnum tradeState = transaction.getTradeState();
			if (Transaction.TradeStateEnum.SUCCESS == tradeState) {
				//用户支付成功
				return true;
			}
		}
		return false;
	}


	/**
	 * 获取微信小程序拉起本地微信支付所需要参数
	 *
	 * @param paymentType 支付类型：支付类型：1301-订单 1302-充值
	 * @param orderNo 订单编号
	 * @return 小程序拉调用wx.requestPayment(Object object)需要参数
	 */
	@Override
	public Map<String, Object> getWxPrePayParams(String paymentType, String orderNo) {
		Long userId = AuthContextHolder.getUserId();
		//1.将本次交易记录保存到本地交易表
		PaymentInfo paymentInfo = paymentInfoService.savePaymentInfo(paymentType, orderNo, userId);
		//2.调用微信SDK获取小程序支付所需参数
		//2.1 构建调用微信接口业务对象
		JsapiServiceExtension jsapiService = new JsapiServiceExtension.Builder().config(rsaAutoCertificateConfig).build();
		//2.2 构建预支付请求对象
		PrepayRequest prepayRequest = new PrepayRequest();
		Amount amount = new Amount();
		//2.2.1 设置预支付订单金额 单位：分 TODO开发接口暂时硬编码1分 实际应该从paymentInfo对象中获取
		amount.setTotal(1);
		prepayRequest.setAmount(amount);
		prepayRequest.setAppid(wxPayV3Config.getAppid());
		prepayRequest.setMchid(wxPayV3Config.getMerchantId());
		prepayRequest.setDescription(paymentInfo.getContent());
		prepayRequest.setNotifyUrl(wxPayV3Config.getNotifyUrl());
		//2.3 TODO 目前小程序未发布，开发阶段必选设置付款人（真正付款只有应用开发者列表中微信账户才有权限）
		Payer payer = new Payer();
		payer.setOpenid("odo3j4qp-wC3HVq9Z_D9C0cOr0Zs");
		prepayRequest.setPayer(payer);
		//2.2.2 商户端订单编号
		prepayRequest.setOutTradeNo(paymentInfo.getOrderNo());
		//2.3 调用下单方法（小程序所需参数），得到应答
		PrepayWithRequestPaymentResponse response = jsapiService.prepayWithRequestPayment(prepayRequest);
		if (response != null) {
			Map<String, Object> mapResult = new HashMap<>();
			mapResult.put("timeStamp", response.getTimeStamp());
			mapResult.put("package", response.getPackageVal());
			mapResult.put("paySign", response.getPaySign());
			mapResult.put("signType", response.getSignType());
			mapResult.put("nonceStr", response.getNonceStr());
			return mapResult;
		}
		return null;
	}
}
